package com.memorypalace.deck.biz;

import java.util.ArrayList;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.ibatis.logging.slf4j.Slf4jImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.google.gson.Gson;
import com.memorypalace.deck.mapper.CardMapper;
import com.memorypalace.deck.mapper.DeckMapper;
import com.memorypalace.deck.mapper.NoteMapper;
import com.memorypalace.deck.mapper.NoteTypeMapper;
import com.memorypalace.deck.vo.DeckNoteNoteTypeCardStyleCard;
import com.memorypalace.deck.vo.DeckQueryPageBean;
import com.memorypalace.deck.vo.NoteAndCardStyleId;
import com.memorypalace.deck.vo.NoteNoteTypeCardStyle;
import com.memorypalace.deck.vo.ScreenConditions;
import com.memorypalace.deck.vo.ScreenInteger;
import com.memorypalace.pojo.Card;
import com.memorypalace.pojo.CardStudyRecord;
import com.memorypalace.pojo.CardStyle;
import com.memorypalace.pojo.Deck;
import com.memorypalace.pojo.Note;
import com.memorypalace.pojo.NoteType;
import com.memorypalace.pojo.PageBean;
import com.memorypalace.pojo.StudyList;
import com.memorypalace.pojo.StudyScheme;
import com.memorypalace.study.mapper.StudySchemeMapper;
import com.memorypalace.study.mapper.CardStudyRecordMapper;

@Service("deckBiz")
public class DeckBizImpl implements IDeckBiz {

	@Autowired
	private DeckMapper deckMapper;
	@Autowired
	private NoteMapper noteMapper;
	@Autowired
	private StudySchemeMapper studySchemeMapper;
	@Autowired
	private CardStudyRecordMapper csrMapper;
	@Autowired
	private CardMapper cardMapper;

	@Override
	public DeckQueryPageBean getQueryPagedDataDecks(DeckQueryPageBean bean) {
		List<Deck> deckList = deckMapper.getQueryPagedDataDecks(bean);
		Integer count = deckMapper.getQueryDataCountDecks(bean);
		bean.setData(deckList);
		bean.setRecordNum(count);
		return bean;

	}

	@Autowired
	private NoteTypeMapper noteTypeMapper;


	@Override
	public List<DeckNoteNoteTypeCardStyleCard> getDeck_Note_NoteType_CardStyle_CardByUserId(String userId) {
		// String userId = "c34487b4-35e3-11e7-8e4c-e18a12b866d4";
		System.out.println("userId:" + userId);
		List<Deck> deckList = deckMapper.getDecksByUserId(userId);
		List<DeckNoteNoteTypeCardStyleCard> cardInDeckList = new ArrayList<DeckNoteNoteTypeCardStyleCard>();
		if (deckList != null) {
			for (Deck deck : deckList) {
				System.out.println("deck:" + deck);
				List<Note> noteList = deck.getNoteList();
				if (noteList.size() >= 1 && noteList.get(0).getNoteTypeId() != null) {
					for (Note note : noteList) {
						// System.out.println("\t"+note);
						NoteType noteType = noteTypeMapper.getNoteTypeWithCardStyleByNoteTypeId(note.getNoteTypeId());
						// NoteType noteType =
						// noteTypeMapper.getNoteTypeByScreenConditions(screenConditions);
						List<CardStyle> cardStyleList = noteType.getCardStyleList();
						if (cardStyleList.size() >= 1 && cardStyleList.get(0).getCardStyleId() != null) {
							for (CardStyle cardStyle : cardStyleList) {
								NoteAndCardStyleId nc = new NoteAndCardStyleId(note.getNoteId(),
										cardStyle.getCardStyleId());
								Card card = cardMapper.getCardByNoteAndCardStyleId(nc);
								if (card != null) {
									System.out.println("-----");
									System.out.println("deck:" + deck.getDeckName() + ",note:" + note.getAreaContents()
											+ ",noteType:" + noteType.getNoteTypeName() + ",cardStyle:"
											+ cardStyle.getCardStyleName() + ",card:" + card.getCardHardFactory());
									deck.setNoteList(null);
									note.setNoteType(null);
									noteType.setCardStyleList(null);
									DeckNoteNoteTypeCardStyleCard cardInDeck = new DeckNoteNoteTypeCardStyleCard(deck,
											note, noteType, cardStyle, card);
									System.out.println(cardInDeck);
									cardInDeckList.add(cardInDeck);
								}
							}
							// note.setNoteType(noteType);
						}
					}
				}
			}
		}

		return cardInDeckList;
	}

	
	
	@Override
	/**
	 * 给studyList设置新/旧卡片列表/个数,
	 */
	public void getDeck_Note_NoteType_CardStyle_CardByStudyList(StudyList studyList) {
		// 查找新的,每次查询学习方案中新卡片的限制个数
		// ScreenConditions screenConditions = new ScreenConditions();
		List<DeckNoteNoteTypeCardStyleCard> cardInDeckList = new ArrayList<DeckNoteNoteTypeCardStyleCard>();
		// 筛选方案和学习方案
		ScreenConditions screenConditions = studyList.getScreenConditions();
		StudyScheme studyScheme = studyList.getStudyScheme();
		if(studyScheme == null || studyScheme.getNewCardStudyScheme() == null){
			studyScheme = studySchemeMapper.getStudySchemeWithAllSchemeById(studyList.getStudySchemeId());
		}
		// 查找变量记录
		Integer foundNewCount = 0;
		Integer totalNewCount = studyScheme.getNewCardStudyScheme().getNewCardCount();
		Integer foundReviewCount = 0;
		Integer totalReviewCount = studyScheme.getReviewCardStudyScheme().getMaxReviewCount();
		// 查找结果收集
		List<DeckNoteNoteTypeCardStyleCard> newCardList = new ArrayList<DeckNoteNoteTypeCardStyleCard>();
		List<DeckNoteNoteTypeCardStyleCard> reviewCardList = new ArrayList<DeckNoteNoteTypeCardStyleCard>();
		// 1.根据userId拿到noteType/cardStyle/card
		List<NoteType> noteTypeList = noteTypeMapper
				.getNoteTypeWithCardStyleByScreenConditionsAndUserId(screenConditions);
		for (NoteType noteType : noteTypeList) {
			for (CardStyle cardStyle : noteType.getCardStyleList()) {
				if (cardStyle.getCardStyleId() != null) {
					screenConditions.setCardStyleId(cardStyle.getCardStyleId());
					// 2.先找新卡片
					Integer pageIndexForNew = 1;
					Integer newRecordNum = null;
					
					while (newRecordNum == null|| (foundNewCount < Math.min(totalNewCount, newRecordNum)) ) {//继续找的条件
						if(newRecordNum == null && foundNewCount >= totalNewCount){
							// 其实已经不需要了
							break;
						}
						// 所有新的个数newRecordNum,已找到的个数foundNewCount,需要找到的个数totalNewCount
							// newRecordNum >= totalNewCount && foundNewCount < totalNewCount
							// newRecordNum < totalNewCount && foundNewCount < newRecordNum
						// 当个数不够时才需要查找新的
						PageBean pageBean = new PageBean();
						pageBean.setCurPage(pageIndexForNew);
						screenConditions.setPageBean(pageBean);
						screenConditions.setCardStyleId(cardStyle.getCardStyleId());
						ScreenInteger cardStudyCount = new ScreenInteger(0, "is", null, null);
						screenConditions.setCardStudyCount(cardStudyCount);
						// screenConditions.getPageBean().setPageCount(pageCount-foundCount);
						// 2.1在查找的符合条件的card中找符合条件的note和deck
						ScreenConditions screenConditionsResult = cardMapper
								.getScreenConditionsByScreenConditions(screenConditions);
						Integer currentCount = 0;
						// 如果一个都没找到,则返回null
						if (screenConditionsResult != null) {
							currentCount = screenConditionsResult.getPageBean().getData().size();
							foundNewCount += currentCount;
						}
						if(newRecordNum == null){
							newRecordNum = cardMapper.getScreenConditionsCountByScreenConditions(screenConditions);
						}
						System.out.println("新的,在第"+pageBean.getCurPage()+"页中已找到:" + foundNewCount + ",还需要:"+(totalNewCount-(foundNewCount-currentCount))+"还可以找:" + newRecordNum);
						// 把新查找的添加到结果收集中
						if (screenConditionsResult != null) {
							if (foundNewCount < totalNewCount) {
								// 如果找到的不够则需继续找,并把找到的加进去
								List<Card> cardList = screenConditionsResult.getPageBean().getData();
								newCardList.addAll(fuseCardList(cardList, noteType, cardStyle));
								pageIndexForNew++;
							} else {// >= 个数已经够了
								List<Card> cardList = screenConditionsResult.getPageBean().getData().subList(0, totalNewCount-(foundNewCount-currentCount));
								newCardList.addAll(fuseCardList(cardList, noteType, cardStyle));
							}
						}
					}
					// 3.再找旧卡片
					Integer pageIndexForReview = 1;
					Integer reviewRecordNum = null;
					while(reviewRecordNum == null|| foundReviewCount < Math.min(totalReviewCount, reviewRecordNum)){
						if(reviewRecordNum == null && foundReviewCount >= totalReviewCount){
							// 其实已经不需要了
							break;
						}
						// cardP.getPageBean().setPageCount(studyScheme.getReviewCardStudyScheme().getMaxReviewCount());
						PageBean pageBean = new PageBean();
						pageBean.setCurPage(pageIndexForReview);
						screenConditions.setPageBean(pageBean);
						screenConditions.setCardStyleId(cardStyle.getCardStyleId());
						ScreenInteger cardStudyCount = new ScreenInteger(1, "greater", null, null);
						screenConditions.setCardStudyCount(cardStudyCount);
						// screenConditions.getPageBean().setPageCount(pageCount-foundCount);
						// 3.1在查找的符合条件的card中找符合条件的note和deck
						ScreenConditions screenConditionsResult = cardMapper
								.getScreenConditionsByScreenConditions(screenConditions);
						Integer currentCount = 0;
						// 如果一个都没找到,则返回null
						if (screenConditionsResult != null) {
							currentCount = screenConditionsResult.getPageBean().getData().size();
							foundReviewCount += currentCount;
						}
						if(reviewRecordNum == null){
							reviewRecordNum = cardMapper.getScreenConditionsCountByScreenConditions(screenConditions);
						}
						System.out.println("旧的,在第"+pageBean.getCurPage()+"页中已找到:" + foundReviewCount + ",还需要:"+(totalReviewCount-(foundReviewCount-currentCount))+"还可以找:" + reviewRecordNum);
						// 把新查找的添加到结果收集中
						if (screenConditionsResult != null) {
							if (foundReviewCount < totalReviewCount) {
								// 如果找到的不够则需继续找,并把找到的加进去
								List<Card> cardList = screenConditionsResult.getPageBean().getData();
								reviewCardList.addAll(fuseCardList(cardList, noteType, cardStyle));
								pageIndexForReview++; // 查找下一页的
							} else {// >= 个数已经够了
								List<Card> cardList = (List<Card>) screenConditionsResult.getPageBean().getData().subList(0, totalReviewCount-(foundReviewCount-currentCount));
								reviewCardList.addAll(fuseCardList(cardList, noteType, cardStyle));
							}
						}
					}
				}
			}
		}
		Gson g = new Gson();
		System.out.println("screenCondition:"+screenConditions.getDeckName().getValue());
		System.out.println("newlist:"+g.toJson(newCardList));
		System.out.println("reviewlist:"+g.toJson(reviewCardList));
		studyList.setNewCardList(newCardList);
		studyList.setNewCard(newCardList.size());
		studyList.setReviewCardList(reviewCardList);
		studyList.setOldCard(reviewCardList.size());	
	}
	/**
	 * @param cardList 每一个card有note和deck
	 * @param noteType noteType有cardStyleList
	 * @return
	 */
	private List<DeckNoteNoteTypeCardStyleCard> fuseCardList(List<Card> cardList,NoteType noteType,CardStyle cardStyle){
		List<DeckNoteNoteTypeCardStyleCard> list = new ArrayList<DeckNoteNoteTypeCardStyleCard>(); 
		for (Card card : cardList) {
			DeckNoteNoteTypeCardStyleCard cardInDeck = new DeckNoteNoteTypeCardStyleCard(card.getDeck(),card.getNote(),noteType,cardStyle,card);
			cardInDeck.getCard().setNote(null);
			cardInDeck.getCard().setDeck(null);
			cardInDeck.getNoteType().setCardStyleList(null);
			list.add(cardInDeck);
		}
		return list;
	}
	
	@Override
	/**
	 * 给studyList设置新/旧卡片列表/个数,
	 */
	public void getDeck_Note_NoteType_CardStyle_CardCountByStudyList(StudyList studyList) {
		// 查找新的,每次查询学习方案中新卡片的限制个数
		// 筛选方案和学习方案
		ScreenConditions screenConditions = studyList.getScreenConditions();
		StudyScheme studyScheme = studyList.getStudyScheme();
		if(studyScheme == null || studyScheme.getNewCardStudyScheme() == null){
			studyScheme = studySchemeMapper.getStudySchemeWithAllSchemeById(studyList.getStudySchemeId());
		}
		// 查找变量记录
		Integer totalNewCount = studyScheme.getNewCardStudyScheme().getNewCardCount();
		Integer newCountCanFind = 0;
		Integer totalReviewCount = studyScheme.getReviewCardStudyScheme().getMaxReviewCount();
		Integer reviewCountCanFind = 0;
		// 查找结果收集
		List<DeckNoteNoteTypeCardStyleCard> newCardList = new ArrayList<DeckNoteNoteTypeCardStyleCard>();
		List<DeckNoteNoteTypeCardStyleCard> reviewCardList = new ArrayList<DeckNoteNoteTypeCardStyleCard>();
		// 1.根据userId拿到noteType/cardStyle/card
		List<NoteType> noteTypeList = noteTypeMapper
				.getNoteTypeWithCardStyleByScreenConditionsAndUserId(screenConditions);
		for (NoteType noteType : noteTypeList) {
			for (CardStyle cardStyle : noteType.getCardStyleList()) {
				if (cardStyle.getCardStyleId() != null) {
					screenConditions.setCardStyleId(cardStyle.getCardStyleId());
					// 2.先找新卡片
					Integer pageIndexForNew = 1;
					Integer newRecordNum = null;
					// 配置当前的筛选条件
					screenConditions.setCardStyleId(cardStyle.getCardStyleId());
					ScreenInteger cardStudyCountIsNew = new ScreenInteger(0, "is", null, null);
					screenConditions.setCardStudyCount(cardStudyCountIsNew);
					// 根据筛选条件拿到个数
					newRecordNum = cardMapper.getScreenConditionsCountByScreenConditions(screenConditions);
					newCountCanFind+=newRecordNum;
					// 3.再找旧卡片
					Integer pageIndexForReview = 1;
					Integer reviewRecordNum = null;
					// 配置当前的筛选条件
					screenConditions.setCardStyleId(cardStyle.getCardStyleId());
					ScreenInteger cardStudyCountIsReview = new ScreenInteger(1, "greater", null, null);
					screenConditions.setCardStudyCount(cardStudyCountIsReview);
					// 根据筛选条件拿到个数
					reviewRecordNum = cardMapper.getScreenConditionsCountByScreenConditions(screenConditions);
					reviewCountCanFind += reviewRecordNum;
				}
			}
		}
		studyList.setNewCard(Math.min(totalNewCount, newCountCanFind));
		studyList.setOldCard(Math.min(totalReviewCount, reviewCountCanFind));
//		System.out.println("screenCondition:"+screenConditions.getDeckName().getValue());
		System.out.println("newCount:"+studyList.getNewCard());
		System.out.println("oldCount:"+studyList.getOldCard());
	}
	
	@Override
	public Boolean addDeck(Deck deck) {
		try {
			deckMapper.addDeck(deck);
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}

	}

	@Override

	public List<Deck> getDecksByUserId(String userId) {
		return deckMapper.getDecksByUserId(userId);
	}

	@Override
	public Deck getDecksByDeckId(String deckId) {
		return deckMapper.getDecksByDeckId(deckId);
	}


	public Boolean modifyDeck(Deck deck) {
		try {
			deckMapper.modifyDeck(deck);
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}

	}

	@Override
	public Boolean deleteDeck(String deckId) {
		try {
			deckMapper.deleteDeck(deckId);
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}

	}

	@Override
	public List<Card> getCardByNoteId(String noteId) {
		List<Card> cardList = cardMapper.getCardByNoteId(noteId);
		return cardList;
	}

	@Override
	public List<CardStyle> getCardStyleByNotetyId(String noteTypeId) {
		List<CardStyle> cardStyleList = cardMapper.getCardStyleByNotetyId(noteTypeId);
		return cardStyleList;
	}

	@Override
	public List<NoteNoteTypeCardStyle> getNoteNoteTypeCardStyle(String deckId) {
		// TODO Auto-generated method stub
		return deckMapper.getNoteNoteTypeCardStyle(deckId);
	}

	@Override
	public Set<Deck> getRecentDecksByUserId(String userId) {
		
		Set<Deck> decks=new HashSet<>();
		Set<Deck> deckInThree=new HashSet<>();
		
		List<CardStudyRecord> cardStudyRecordList=csrMapper.getCardStudyRecordInThreeDays(userId);
		for (CardStudyRecord cardStudyRecord : cardStudyRecordList) {
			Card card=cardMapper.getCardByCardId(cardStudyRecord.getCardId());
			Note note=noteMapper.getNoteWithDeckAndNoteTypeById(card.getNoteId());
			Deck deck=deckMapper.getDecksByDeckId(note.getDeckId());
				decks.add(deck);	
		}
		for (Deck deck : decks) {
			if(deckInThree.size()<=3){
				deckInThree.add(deck);
			}else{
				break;
			}
		}
		
		
		/*List<Deck> decks = new ArrayList<Deck>();
		List<Deck> deckList = deckMapper.getDecksByUserId(userId);
		for (Deck deck : deckList) {
			List<NoteCardCardStudyRecord> ncrList = deckMapper.getNoteCardCardStudyRecord(deck.getDeckId());
			for (NoteCardCardStudyRecord noteCardCardStudyRecord : ncrList) {
				// new Date()-
				// noteCardCardStudyRecord.getCardStudyRecord().getStudyTime()<=3tian

				long pastTime = System.currentTimeMillis() - 3 * 24 * 60 * 60 * 1000;
				Date d1 = new Date(pastTime);
				Date d2 = noteCardCardStudyRecord.getCardStudyRecord().getStudyTime();
			
				// 显示三天内学习过的牌组,最多显示三条
				if (decks.size() <= 3) {
					if (d1.getTime() <= d2.getTime()) {
						decks.add(deck);
					}
				}
				break;
			}
		}*/
		
		return deckInThree;
	}
}
